import { Graph, Addon, FunctionExt, Shape, ToolsView } from '@antv/x6';
import { message,Modal } from 'antd';
import { saveGraph } from '../../flow/saveGraph';
import { checkSlide } from './checkSlide';
import UserSession from '@/UserSession';
import knowledgeHome from '@/services/knowledgeHome';

export default class FlowGraph {
  public static graph: Graph;
  public static dnd: Addon.Dnd;
  private static stencil: Addon.Stencil;
  public static selectCells: [];

  public static init() {
    this.graph = new Graph({
      container: document.getElementById('container')!,
      width: 2000,
      height: 1000,
      grid: {
        size: 10,
        visible: true,
        type: 'dot',
        args: [
          {
            color: '#cccccc',
            thickness: 1,
          },
          {
            color: '#cccccc',
            thickness: 1,
            factor: 4,
          },
        ],
      },
      selecting: {
        enabled: true,
        multiple: true,
        rubberband: true,
        modifiers: 'shift',
        movable: true,
        showNodeSelectionBox: true,
        filter: ['groupNode'],
      },
      connecting: {
        anchor: 'center',
        connectionPoint: 'anchor',
        allowBlank: false,
        highlight: !UserSession.isSystemKnowledge(),
        snap: true,
        allowMulti:false,
        allowPort:!UserSession.isSystemKnowledge(),
        createEdge() {
          return new Shape.Edge({
            attrs: {
              line: {
                stroke: '#0A172A',
                strokeWidth: 1,
                targetMarker: {
                  name: 'classic',
                  size: 8,
                },
              },
              isClick:false
            },
            router: {
              name: 'manhattan',
              args: {
                padding: 1,
              },
            },
            zIndex: 0,
          });
        },
        validateEdge({ edge, type, previous }) {
          // const query = window.location.search.substring(1);
          // const vars = query.split('&');
          // const id = vars[0].split('=')[1];

          if (checkSlide()) {
            message.error('不支持此连线方式');
            return false;
          }
          const flag = saveGraph();
          return flag;
        },
        validateConnection({ sourceView, targetView, sourceMagnet, targetMagnet }) {
          const ports = document.getElementById('container').querySelectorAll('.x6-port-body') as NodeListOf<SVGAElement>;
          for (let i = 0, len = ports.length; i < len; i = i + 1) {
            ports[i].style.visibility = true ? 'visible' : 'hidden';
          }
          if (sourceView === targetView) {
            return false;
          }
          if (!sourceMagnet) {
            return false;
          }
          if (!targetMagnet) {
            return false;
          }

          /**
           * 当目标链接桩组为out组时，表示该链接桩只能输出，不能输入，故不能链接
           */
          if(targetMagnet.getAttribute('port-group').indexOf('out') !== -1){
            return false
          }

          /**
           * 当开始链接桩组为in组时，表示该链接桩只能输入，不能输出，故不能链接
           */
          if(sourceMagnet.getAttribute('port-group').indexOf('in') !== -1){
            return false
          }
          return true;
        },
      },
      highlighting: {
        magnetAvailable: {
          name: 'stroke',
          args: {
            padding: 4,
            attrs: {
              strokeWidth: 4,
              stroke: 'rgba(223,234,255)',
            },
          },
        },
      },
      snapline: true,
      history: true,
      scroller: {
        enabled: true,
        pannable: true,
        autoResize: true,
        pageVisible: true,
        pageBreak: true,
        minVisibleHeight: 400,
        minVisibleWidth: 500,
      },
      clipboard: {
        enabled: true,
      },
      keyboard: {
        enabled: true,
      },
      embedding: {
        enabled: true,
        findParent({ node }) {
          const bbox = node.getBBox();
          return this.getNodes().filter(node => {
            // 只有 data.parent 为 true 的节点才是父节点
            const data = node.getData<any>();
            if (data && data.parent) {
              const targetBBox = node.getBBox();
              return bbox.isIntersectWithRect(targetBBox);
            }
            return false;
          });
        },
      },
      interacting:{
        arrowheadMovable:!UserSession.isSystemKnowledge()
      },
    });
    this.initEvent();
    this.bindKey();
    return this.graph;
  }

  public static initDnd() {
    this.dnd = new Addon.Dnd({
      target: this.graph,
      scaled: false,
      animation: true,
      validateNode: (droppingNode, options) => {
        const nodesArray = this.graph.getNodes();
        const isStartNode = nodesArray.filter(item => item.label === 'start');
        if (isStartNode.length > 0 && droppingNode.label === 'start') {
          message.error('开始节点只能存在一个');
          return false;
        };
        knowledgeHome.postFormFlowNodeAdd();
        const flag = saveGraph('', droppingNode.toJSON());
        return flag;
      },
    });
    return this.dnd;
  }

  // public static getDialogId() {
  //   const query = window.location.search.substring(1);
  //   const vars = query.split('&');
  //   const id = vars[0].split('=')[1];
  //   return id;
  // }

  private static showPorts(ports: NodeListOf<SVGAElement>, show: boolean) {
    for (let i = 0, len = ports.length; i < len; i = i + 1) {
      ports[i].style.visibility = show && !UserSession.isSystemKnowledge() ? 'visible' : 'hidden';
    }
  }

  private static bindKey(){
    /**
     * 绑定delete键删除节点
     */
    this.graph.bindKey('delete', () => {
      if(UserSession.isSystemKnowledge()){
        return;
      }
      const cells = this.graph.getSelectedCells();
      const graph = this.graph;
      if(cells){
        Modal.confirm({
          title: '是否确认删除？',
          okText: '确定',
          okType: 'danger',
          cancelText: '取消',
          onOk() {
            graph.removeCells(cells);
          },
        })
      }
    });
  }

  private static initEvent() {
    const { graph } = this;
    const container = document.getElementById('container')!;
    /**
     * 节点双击改变label名字
     */
    // graph.on('node:dblclick', ({ cell, view }) => {
    //   if(UserSession.isSystemKnowledge()){
    //     return;
    //   }
    //   const oldText = cell.attr('text/textWrap/text') as string;
    //   const elem = view.container.querySelector('.x6-edit-text') as HTMLElement;
    //   if (elem == null) {
    //     return;
    //   }
    //   cell.attr('text/style/display', 'none');
    //   if (elem) {
    //     this.graph.unbindKey('delete');
    //     this.graph.unbindKey('backspace');
    //     elem.style.display = '';
    //     elem.contentEditable = 'true';
    //     elem.innerText = oldText;
    //     if (document.selection) {
    //       const range = document.body.createTextRange();
    //       range.moveToElementText(elem);
    //       range.select();
    //     } else if (window.getSelection) {
    //       const range = document.createRange();
    //       range.selectNodeContents(elem);
    //       window.getSelection().removeAllRanges();
    //       window.getSelection().addRange(range);
    //     }
    //     elem.focus();
    //   }
    //   const onBlur = () => {
    //     this.bindKey();
    //     cell.attr('text/textWrap/text', elem.innerText);
    //     cell.attr('text/style/display', '');
    //     elem.style.display = 'none';
    //     elem.contentEditable = 'false';
    //     saveGraph();
    //   };
    //   elem.addEventListener('blur', () => {
    //     onBlur();
    //     elem.removeEventListener('blur', onBlur);
    //   });
    // });

    /**
     * 鼠标悬浮展示链接桩
     */
    graph.on(
      'node:mouseenter',
      FunctionExt.debounce(node => {
        const ports = container.querySelectorAll('.x6-port-body') as NodeListOf<SVGAElement>;
        this.showPorts(ports, true);
      }),
      500
    );

    /**
     * 鼠标离开隐藏链接桩
     */
    graph.on('node:mouseleave', () => {
      const ports = container.querySelectorAll('.x6-port-body') as NodeListOf<SVGAElement>;
      this.showPorts(ports, false);
    });

    graph.on('node:collapse', ({ node, e }) => {
      e.stopPropagation();
      node.toggleCollapse();
      const collapsed = node.isCollapsed();
      const cells = node.getDescendants();
      cells.forEach(n => {
        if (collapsed) {
          n.hide();
        } else {
          n.show();
        }
      });
    });

    graph.on('node:embedded', ({ cell }) => {
      if (cell.shape !== 'groupNode') {
        cell.toFront();
      }
    });

    /**
     * 鼠标悬浮边 边变粗
     */
    graph.on('edge:mouseenter', ({ cell }) => {
      cell.setAttrs({
        line: {
          strokeWidth: 3,
        },
      });
      cell.addTools([
        {
          name: 'target-arrowhead',
          args: {
            attrs: {
              fill: '#0A172A',
            },
          },
        },
      ])
    });

    /**
     * 鼠标点击边 边变粗
     */
    graph.on('edge:click', ({ cell }) => {
      const edges = this.graph.getEdges();
      for(const item of edges){
        if(item.id === cell.id){
          item.setAttrs({
            line: {
              strokeWidth: 3,
            },
            isClick:true
          });
        }else {
          item.setAttrs({
            line: {
              strokeWidth: 1,
            },
            isClick:false
          });
        }
      }
    });

    /**
     * 鼠标离开边 恢复
     */
    graph.on('edge:mouseleave', ({ cell }) => {
      if(!cell.getAttrs().isClick){
        cell.setAttrs({
          line: {
            strokeWidth: 1,
          },
        });
      }
      cell.removeTools()
    });

    /**
     * 鼠标点击空白背景 链接桩隐藏 ×隐藏 边恢复
     */
    graph.on('blank:click', ({ e, x, y }) => {
      const ports = container.querySelectorAll('.x6-port-body') as NodeListOf<SVGAElement>;
      this.showPorts(ports, false);
      const cells = graph.getCells();
      cells.map(item => item.removeTools());
      cells.map(item => item.removeAttrByPath('image'));
      cells.map(item => {
        if(item.isEdge()){
          item.setAttrs({
            line: {
              strokeWidth: 1,
            },
            isClick:false
          });
        }
      })
    });

    // 节点/边的删除
    graph.on('cell:removed', ({ cell, options }) => {
      if(!this.selectCells){
        // 鼠标悬浮在节点上 未选中节点 点击左上角×按钮进行的删除
        saveGraph();
      }else {// 节点或边被选中 然后进行的删除 需要进行选中的节点和删除的节点做判断 当选中的节点都删除时 再调用保存接口 用于防止删不干净
        let selectData =  [];
        selectData = this.selectCells.filter(item => item.id !== cell.id);
        this.selectCells = selectData;
        if(this.selectCells.length === 0){
          saveGraph();
        }
      }

    });

    // 自定义节点删除事件
    graph.on('node:delete', ({ view, e }) => {
      e.stopPropagation()
      Modal.confirm({
        title: '是否确认删除节点？',
        okText: '确定',
        okType: 'danger',
        cancelText: '取消',
        onOk() {
          const list = graph.getSelectedCells()
          //若当前选中了多个节点 或 当前选中的一个节点不是当前要删除的节点 则不允许删除 提示先取消当前选中
          if(list.length > 1 || list.length == 1 && list[0].id != view.cell.id){
            message.info("有选中的节点未被删除，请先取消选中")
          }else{
            knowledgeHome.postFormFlowNodeDel()
            view.cell.remove()
          }
        },
      })
    })

    // 监听选中的节点 将选中的节点保存下来 用于判断多选删除时的保存
    graph.on('cell:selected', ({ cell, options }) => {
      this.selectCells = graph.getSelectedCells();
    });

    /**
     * 边双击添加label
     */
    // graph.on('edge:dblclick', ({ edge, e }) => {
    //   const p = graph.clientToGraph(e.clientX, e.clientY);
    //   const container = document.getElementById('container');
    //   const editorParent = ToolsView.createElement('div', false) as HTMLDivElement;
    //   editorParent.style.position = 'absolute';
    //   editorParent.style.left = `${p.x}px`;
    //   editorParent.style.top = `${p.y}px`;
    //   editorParent.style.width = `${80}px`;
    //   editorParent.style.height = `${20}px`;
    //   editorParent.style.display = 'flex';
    //   editorParent.style.alignItems = 'center';
    //   editorParent.style.textAlign = 'center';
    //   const editorContent = ToolsView.createElement('div', false) as HTMLDivElement;
    //   editorContent.contentEditable = 'true';
    //   editorContent.style.width = '100%';
    //   editorContent.style.outline = 'none';
    //   editorContent.style.backgroundColor = '#fff';
    //   editorContent.style.border = '1px solid #ccc';
    //   editorParent.appendChild(editorContent);
    //   container.appendChild(editorParent);
    //
    //   const oldText = edge.getLabels();
    //   editorContent.innerText = oldText[0] ? oldText[0].attrs.label.text : '';
    //   if (document.selection) {
    //     const range = document.body.createTextRange();
    //     range.moveToElementText(editorContent);
    //     range.select();
    //   } else if (window.getSelection) {
    //     const range = document.createRange();
    //     range.selectNodeContents(editorContent);
    //     window.getSelection().removeAllRanges();
    //     window.getSelection().addRange(range);
    //   }
    //   editorContent.focus();
    //
    //   const onBlur = () => {
    //     edge.setLabels(editorContent.innerText);
    //     editorParent.style.display = 'none';
    //     saveGraph(this.getDialogId());
    //   };
    //   editorContent.addEventListener('blur', () => {
    //     onBlur();
    //     editorContent.removeEventListener('blur', onBlur);
    //   });
    // });
  }
}
